<script lang="ts">
	import { userIdentity } from '$lib/AniList/identity';
	import { user } from '$lib/AniList/user';
	import { nbsp } from '$lib/Utility/html';
	import type { Badge } from '$lib/Database/badges';
	// import { domToBlob } from 'modern-screenshot';
	import { onMount } from 'svelte';
	import HeadTitle from '$lib/Home/HeadTitle.svelte';
	import { databaseTimeToDate, dateToDatabaseTime } from '$lib/Utility/time';
	import Loading from '$lib/Utility/Loading.svelte';
	import root from '$lib/Utility/root.js';
	import tooltip from '$lib/Tooltip/tooltip.js';
	import proxy from '$lib/Utility/proxy.js';
	import cdn from '$lib/Utility/cdn.js';
	import locale from '$stores/locale.js';
	// import { io } from 'socket.io-client';

	export let data;

	let editMode = false;
	let currentUserIdentity: ReturnType<typeof userIdentity>;
	let error: null | string;
	// const socket = io();
	let badgesPromise: Promise<Response>;
	let awcPromise: Promise<Response>;
	// let dark = true;
	// let transparent = false;
	let confirmDelete = 0;
	let selectedBadge: Badge | undefined = undefined;
	let loadError: string | null = null;
	// let badgeCount = 0;

	// $: downloadDisabled = badgeCount > 20;

	type GroupedBadges = { [key: string]: Badge[] };

	interface AWCBadge {
		link: string;
		description: string;
		image: string;
	}

	interface AWCBadgesGroup {
		group: string;
		badges: AWCBadge[];
	}

	onMount(async () => {
		// socket.on('badges', (message) => (badges = message));

		const badger = await user(data.username);

		if (!badger) {
			loadError = 'User not found.';

			return;
		}

		badgesPromise = fetch(root(`/api/badges?id=${badger.id}`));
		awcPromise = fetch(proxy(`https://awc.moe/challenger/${badger.name}`));

		if (data.user) {
			currentUserIdentity = userIdentity(data.user);

			// socket.emit('badges', data.user);
		} else {
			currentUserIdentity = new Promise((resolve) =>
				resolve({
					name: 'Guest',
					id: -1,
					avatar: 'https://s4.anilist.co/file/anilistcdn/user/avatar/large/default.png'
				})
			);
		}
	});

	const fallback = (event: Event, image: string | undefined) =>
		((event.target as HTMLImageElement).src = image || '');

	// const awcBadges = (awcResponse: string): AWCBadge[] => {
	// 	return Array.from(
	// 		new DOMParser().parseFromString(awcResponse, 'text/html').querySelectorAll('.badge-display a')
	// 	).map((b) => {
	// 		const badge = b as HTMLAnchorElement;
	// 		const image = badge.querySelector('img') as HTMLImageElement;

	// 		return {
	// 			link: badge.href,
	// 			description: image.alt,
	// 			image: image.src
	// 		};
	// 	});
	// };

	const awcBadgesGrouped = (awcResponse: string): AWCBadgesGroup[] => {
		return Array.from(
			new DOMParser().parseFromString(awcResponse, 'text/html').querySelectorAll('.container')
		)
			.map((c) => {
				const container = c as HTMLDivElement;
				const header = container.querySelector('.container-header') as HTMLDivElement;

				if (!header) return;

				if (!['Anime', 'Manga', 'Special'].includes(header.innerText)) return;

				if (header.innerText === 'Special') {
					return {
						group: header.innerText,
						badges: Array.from(container.querySelectorAll('.badge-display img')).map((b) => {
							const badge = b as HTMLImageElement;

							return {
								link: '#',
								description: badge.alt,
								image: badge.src.includes('placeholder')
									? cdn('https://awc.moe/static/images/badge-placeholder.png')
									: badge.src
							};
						})
					};
				}

				return {
					group: header.innerText,
					badges: Array.from(container.querySelectorAll('.badge-display a')).map((b) => {
						const badge = b as HTMLAnchorElement;
						const image = badge.querySelector('img') as HTMLImageElement;

						return {
							link: badge.href,
							description: image.alt,
							image: image.src.includes('placeholder')
								? cdn('https://awc.moe/static/images/badge-placeholder.png')
								: image.src
						};
					})
				};
			})
			.filter((b) => b !== undefined) as AWCBadgesGroup[];
	};

	const submitBadge = () => {
		const imageURL = document.querySelector('input[name="image_url"]') as HTMLInputElement;
		const activityURL = document.querySelector('input[name="activity_url"]') as HTMLInputElement;
		const description = document.querySelector('input[name="description"]') as HTMLInputElement;
		const time = document.querySelector('input[type="datetime-local"]') as HTMLInputElement;
		const category = document.querySelector('input[name="category"]') as HTMLInputElement;

		if (!imageURL.value) {
			error = 'Image URL cannot be empty.';

			return;
		}

		if (
			!imageURL.value.startsWith('http') ||
			(activityURL.value.length > 0 && !activityURL.value.startsWith('http'))
		) {
			error = 'URLs must start with http or https.';

			return;
		}

		badgesPromise = fetch(
			`/api/badges?image=${encodeURIComponent(imageURL.value)}&post=${encodeURIComponent(
				activityURL.value || '#'
			)}${
				description.value.length > 0 ? `&description=${encodeURIComponent(description.value)}` : ''
			}${category.value.length > 0 ? `&category=${encodeURIComponent(category.value)}` : ''}${
				time.valueAsDate ? `&time=${encodeURIComponent(dateToDatabaseTime(time.valueAsDate))}` : ''
			}${
				selectedBadge && selectedBadge.id ? `&update=${encodeURIComponent(selectedBadge.id)}` : ''
			}`,
			{
				method: 'PUT'
			}
		);

		error = null;
		imageURL.value = '';
		activityURL.value = '';
		description.value = '';
		category.value = '';
		selectedBadge = undefined;
	};

	const removeBadge = (badge: Badge) => {
		if (!badge.id) return;

		if (confirmDelete === badge.id * 2) {
			confirmDelete = 0;
		} else if (confirmDelete / 4 === badge.id) {
			confirmDelete = badge.id * 2;

			return;
		} else {
			confirmDelete = badge.id * 2;

			return;
		}

		(document.querySelector(`#badge-${badge.id}`) as HTMLAnchorElement).style.display = 'none';
		selectedBadge = undefined;
		badgesPromise = fetch(root(`/api/badges?id=${badge.id}`), {
			method: 'DELETE'
		});
	};

	// const screenshot = async () => {
	// 	let element = document.querySelector('#badges') as HTMLElement;

	// 	element.classList.add('invert');

	// 	if (element !== null) {
	// 		domToBlob(element, {
	// 			style: {
	// 				backgroundColor: transparent ? 'transparent' : dark ? '#0b1622' : '#edf1f5'
	// 			},
	// 			quality: 1,
	// 			scale: 2,
	// 			fetch: {
	// 				requestInit: {
	// 					mode: 'cors'
	// 				}
	// 				// bypassingCache: true
	// 			}
	// 		}).then((blob) => {
	// 			const downloadWrapper = document.createElement('a');
	// 			const wrappedImageButton = document.getElementById(
	// 				'wrapped-image-download'
	// 			) as HTMLAnchorElement;
	// 			const image = document.createElement('img');
	// 			const object = (window.URL || window.webkitURL || window || {}).createObjectURL(blob);

	// 			downloadWrapper.href = object;
	// 			downloadWrapper.target = '_blank';
	// 			image.src = object;

	// 			downloadWrapper.appendChild(image);

	// 			if (wrappedImageButton !== null) {
	// 				wrappedImageButton.href = object;
	// 			}

	// 			const wrappedFinal = document.getElementById('wrapped-final');

	// 			if (wrappedFinal !== null) {
	// 				wrappedFinal.innerHTML = '';
	// 				wrappedFinal.appendChild(downloadWrapper);
	// 			}

	// 			downloadWrapper.click();
	// 		});

	// 		await new Promise((resolve) => setTimeout(resolve, 1000));

	// 		element.classList.remove('invert');
	// 	}
	// };

	const groupBadges = (badges: Badge[]) => {
		const groupedBadges: GroupedBadges = {};

		// badgeCount = badges.length;

		badges.forEach((badge) => {
			if (!badge.category) badge.category = 'Uncategorised';

			if (!groupedBadges[badge.category]) groupedBadges[badge.category] = [];

			groupedBadges[badge.category].push(badge);
		});

		return Object.entries(groupedBadges)
			.sort((a, b) => a[1].length - b[1].length)
			.reduce((set: GroupedBadges, [key, value]) => {
				set[key] = value;

				return set;
			}, {});
	};
</script>

<HeadTitle route={`${data.username}'s Badge Wall`} path={`/user/${data.username}`} />

{#if loadError}
	<div class="card">
		{loadError}
	</div>
{:else}
	{#await currentUserIdentity}
		<Loading type="badges" percent={40} />
	{:then identity}
		{@const isOwner = identity && identity.name === data.username}

		{#await badgesPromise}
			<Loading type="user identity" percent={60} />
		{:then badgesResponse}
			{#if badgesResponse}
				{#await badgesResponse.json()}
					<Loading type="badges" percent={80} />
				{:then ungroupedBadges}
					<div id="badges">
						{#await awcPromise then badges}
							{#await badges.text() then text}
								{@const parsedBadges = awcBadgesGrouped(text)}

								{#if parsedBadges.length > 0}
									{#each parsedBadges as group}
										<details open>
											<summary>Anime Watching Club | {group.group}</summary>

											<p />

											<div class="badges">
												{#each group.badges as badge}
													<a
														href={badge.link}
														target="_blank"
														id={`badge-${badge.link}`}
														title={badge.description}
														use:tooltip
													>
														<img
															src={cdn(badge.image)}
															alt={badge.description}
															loading="lazy"
															on:error={(e) => fallback(e, badge.image)}
														/>
													</a>
												{/each}
											</div>
										</details>

										<p />
									{/each}
								{/if}
							{/await}
						{/await}

						{#if ungroupedBadges === null}
							<Loading>
								{@html nbsp('Loading badges ... 50%')}
							</Loading>
						{:else if ungroupedBadges.length === 0}
							<div class="card">
								No due.moe registered badges found for this user. <a
									href={'#'}
									title="This alert does not include AWC badges."
									use:tooltip>?</a
								>
							</div>
						{:else}
							{@const groupedBadges = Object.entries(groupBadges(ungroupedBadges))}

							{#if isOwner}
								<div class="card">
									<a href={root(`/user/${data.username}`)}>{$locale().user.badges.backToProfile}</a>
									<span style="margin: 0 0.625rem;">•</span>
									<button
										on:click={() => {
											if (editMode) selectedBadge = undefined;

											editMode = !editMode;
										}}
									>
										{editMode
											? $locale().user.badges.editMode.disable
											: $locale().user.badges.editMode.enable}
									</button>

									{#if editMode && isOwner}
										{@const groups = groupedBadges
											.map((group) => group[0])
											.filter((group) => group !== 'Uncategorised')}

										<p />

										{#if error}
											<p style="color: red;">{error}</p>
										{/if}

										<input
											type="text"
											placeholder={$locale().user.badges.editMode.imageURL}
											name="image_url"
											minlength="1"
											maxlength="1000"
											size="15"
											value={selectedBadge ? selectedBadge.image : ''}
										/>
										<input
											type="text"
											placeholder={$locale().user.badges.editMode.activityURL}
											name="activity_url"
											minlength="1"
											maxlength="1000"
											size="15"
											value={selectedBadge
												? selectedBadge.post === '#'
													? ''
													: selectedBadge.post
												: ''}
										/>
										<input
											type="text"
											placeholder={$locale().user.badges.editMode.description}
											name="description"
											minlength="1"
											maxlength="1000"
											size="15"
											value={selectedBadge ? selectedBadge.description : ''}
										/>
										<input
											type="text"
											placeholder={$locale().user.badges.editMode.category}
											name="category"
											minlength="1"
											maxlength="1000"
											size="15"
											value={selectedBadge
												? selectedBadge.category === 'Uncategorised'
													? ''
													: selectedBadge.category
												: ''}
											list="categories"
										/>
										{#if groups.length > 0}
											<datalist id="categories">
												{#each groups as group}
													<option value={group} />
												{/each}
											</datalist>
										{/if}
										<button class="button-lined" on:click={submitBadge}
											>{selectedBadge
												? $locale().user.badges.editMode.update
												: $locale().user.badges.editMode.add}</button
										>
										{#if selectedBadge}
											{$locale().user.badges.editMode.or}
											<button
												class="button-lined"
												on:click={() => {
													if (selectedBadge) removeBadge(selectedBadge);
												}}>{$locale().user.badges.editMode.delete}</button
											>
										{/if}
										<span style="float: right;">
											<input
												type="datetime-local"
												value={selectedBadge && selectedBadge.time ? selectedBadge.time : ''}
											/>
											<small>Must be full date and time, defaults to now if any fields empty</small>
										</span>
									{/if}
								</div>
							{/if}

							<p />

							{#each groupedBadges as [category, badges]}
								<details open>
									<summary>{category}</summary>

									<p />

									<div class="badges">
										{#each badges as badge}
											{#if editMode}
												<a
													href={`#`}
													on:click={() => (selectedBadge = badge)}
													id={`badge-${badge.id}`}
													title={`${
														badge.time ? databaseTimeToDate(badge.time).toLocaleString() : ''
													}${badge.description ? `\n${badge.description}` : ''}`}
													use:tooltip
												>
													<img
														src={cdn(badge.image)}
														alt={badge.description}
														loading="lazy"
														on:error={(e) => fallback(e, badge.image)}
													/>
												</a>
											{:else}
												<a
													href={badge.post}
													target="_blank"
													id={`badge-${badge.id}`}
													title={`${
														badge.time ? databaseTimeToDate(badge.time).toLocaleString() : ''
													}${badge.description ? `\n${badge.description}` : ''}`}
													use:tooltip
												>
													<img
														src={cdn(badge.image)}
														alt={badge.description}
														loading="lazy"
														on:error={(e) => fallback(e, badge.image)}
													/>
												</a>
											{/if}
										{/each}
									</div>
								</details>

								{#if groupedBadges[groupedBadges.length - 1][0] !== category}
									<p />
								{/if}
							{/each}
						{/if}
					</div>
				{:catch}
					<div class="card">Could not parse badges</div>
				{/await}
			{:else}
				<Loading type="badges" percent={20} />
			{/if}
		{:catch}
			<div class="card">Could not fetch badges</div>
		{/await}
	{/await}
{/if}

<style>
	/* body {
		margin: 0;
		padding: 0;
		text-align: center;
		background-color: #151f2e;
	} */

	img {
		width: 100%;
		height: auto;
	}

	.badges {
		display: grid;
		grid-template-columns: repeat(auto-fill, minmax(8%, 1fr));
		gap: 0.25rem;
	}

	:global(.invert *) {
		filter: invert(0) !important;
	}
</style>
